package net.guoyixian.admin.shiro;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import net.guoyixian.common.redis.RedisKeyPrefixUtils;
import net.guoyixian.common.redis.RedisService;
import net.guoyixian.common.web.ValidationTimeUtils;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.util.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RedisCache<K, V> implements Cache<K, V> {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	private RedisService redisService;
	
	public RedisCache(RedisService redisService){
		 if (redisService == null) {
	         throw new IllegalArgumentException("Cache argument cannot be null.");
	     }
	     this.redisService = redisService;
	}

	@Override
	public V get(K key) throws CacheException {
		logger.debug("根据key从Redis中获取对象 key [" + key + "]");
		try {
			if (key == null) {
				return null;
			} else {
				// byte[] rawValue = cache.get(getByteKey(key));
				byte[] _key = getByteKey(key);
				
				byte[] sessioninfo = this.redisService.get(_key);
				V value = (V) SerializeUtils.deserialize(sessioninfo);
				return value;
			}
		} catch (Throwable t) {
			throw new CacheException(t);
		}
	}

	@Override
	public V put(K key, V value) throws CacheException {
		logger.debug("根据key从存储 key [" + key + "]");
		try {
			byte[] _key = getByteKey(key);
			byte[] _value = SerializeUtils.serialize(value);
			this.redisService.set(_key, _value,
					(int) ValidationTimeUtils.SESSION_TIME);// 过期时间为秒
			return (V) _value;
		} catch (Throwable t) {
			throw new CacheException(t);
		}
	}

	@Override
	public V remove(K key) throws CacheException {
		logger.debug("从redis中删除 key [" + key + "]");
		try {
            V oldvalue = this.get(key);
            this.redisService.del(getByteKey(key));
            return oldvalue;
        } catch (Throwable t) {
            throw new CacheException(t);
        }
	}

	@Override
	public void clear() throws CacheException {
		logger.debug("从redis中删除所有元素");
		try {
			String key =RedisKeyPrefixUtils.SESSION_ADMIN_PREFIX + "*";
			 this.redisService.del(key);
        } catch (Throwable t) {
            throw new CacheException(t);
        }
		

	}

	@Override
	public int size() {
		Set<byte[]> keys = redisService
				.keys((RedisKeyPrefixUtils.SESSION_ADMIN_PREFIX + "*")
						.getBytes());
		return keys.size();
	}

	@SuppressWarnings("unchecked")
	@Override
	public Set<K> keys() {
		Set<K> keys = (Set<K>) redisService
				.keys((RedisKeyPrefixUtils.SESSION_ADMIN_PREFIX + "*")
						.getBytes());
		return keys;
	}

	@Override
	public Collection<V> values() {
		try {
            Set<byte[]> keys = redisService
    				.keys((RedisKeyPrefixUtils.SESSION_ADMIN_PREFIX + "*")
    						.getBytes());
            if (!CollectionUtils.isEmpty(keys)) {
                List<V> values = new ArrayList<V>(keys.size());
                for (byte[] key : keys) {
                    @SuppressWarnings("unchecked")
					V value = this.get((K)key);
                    if (value != null) {
                        values.add(value);
                    }
                }
                return Collections.unmodifiableList(values);
            } else {
                return Collections.emptyList();
            }
        } catch (Throwable t) {
            throw new CacheException(t);
        }
	}

	/**
	 * 获得byte[]型的key
	 * 
	 * @param key
	 * @return
	 */
	private byte[] getByteKey(K sessionId) {
		String preKey = RedisKeyPrefixUtils.SESSION_ADMIN_PREFIX + sessionId;
		return preKey.getBytes();
	}

}
